"""
auth.py - Simple user authentication (requires session.py).

Reads usernames and passwords from 'passwords.txt' (one user per line,
format: username:password). Stores the logged-in username in the session.
"""

import os
import urllib.parse      # for parsing form data sent by the browser
import session           # our manual cookie session module
import config            # shared constants (e.g., LOGIN_ROUTE, LOGOUT_ROUTE)


# Dictionary that maps usernames to passwords, loaded from passwords.txt
PASSWORDS = {}

def load_passwords(filename='passwords.txt'):
    """Load username:password pairs from a text file."""
    global PASSWORDS
    if not os.path.exists(filename):
        print(f"Warning: '{filename}' not found. No users can log in.")
        return
    with open(filename, 'r') as f:
        for line in f:
            line = line.strip()
            # Skip empty lines or lines without a colon
            if not line or ':' not in line:
                continue
            user, pwd = line.split(':', 1)
            PASSWORDS[user.strip()] = pwd.strip()


# Load the password file as soon as the module is imported
load_passwords()


def parse_post_data(handler):
    """
    Read and parse URL-encoded POST data from the request body.
    Returns a dictionary of form fields (e.g., {'username': 'alice', 'password': 'apple'}).
    """
    # The Content-Length header tells us how many bytes to read
    content_length = int(handler.headers.get('Content-Length', 0))
    if content_length == 0:
        return {}
    # Read exactly that many bytes from the request body
    raw_data = handler.rfile.read(content_length)
    # parse_qs returns lists for each key; we flatten to single values
    data = urllib.parse.parse_qs(raw_data.decode('utf-8'))
    return {k: v[0] for k, v in data.items()}


def is_logged_in(handler):
    """
    Return True if the current session contains a 'user' key.
    The main server uses this to decide whether to allow access.
    """
    # Make sure a session object was attached by the dispatcher
    if not hasattr(handler, 'session') or handler.session is None:
        return False
    return 'user' in handler.session


def redirect_to_login(handler, error=False):
    """
    Send a 302 redirect to the login page.
    If error is True, append ?error=1 so the page can show an error message.
    """
    location = config.LOGIN_ROUTE
    if error:
        location += '?error=1'
    handler.send_response(302)                     # 302 = temporary redirect
    handler.send_header('Location', location)
    handler.end_headers()


def handle_login(handler):
    """
    Process a POST to /login:
      - Extract username and password from the form data.
      - Check them against PASSWORDS.
      - On success: store 'user' in the session, set the session cookie,
        and redirect to the home page.
      - On failure: redirect back to the login page with an error flag.
    """
    # Safety check: the dispatcher should always have called get_session()
    if not hasattr(handler, 'session') or handler.session is None:
        handler.send_error(500, 'No session object')
        return

    data = parse_post_data(handler)
    username = data.get('username', '').strip()
    password = data.get('password', '')

    # Compare against the loaded password file
    if username in PASSWORDS and PASSWORDS[username] == password:
        # Successful login – remember the user in the session
        handler.session['user'] = username
        handler.send_response(302)
        handler.send_header('Location', '/')       # redirect to home page
        session.set_session_cookie(handler)        # send cookie if new session
        handler.end_headers()
    else:
        # Login failed – redirect back to login page with an error indicator
        redirect_to_login(handler, error=True)


def handle_logout(handler):
    """
    Log out the current user:
      - Remove the 'user' key from the session.
      - Expire the session cookie.
      - Redirect to the login page.
    """
    # Remove user data from the session (but keep the session itself)
    if hasattr(handler, 'session') and handler.session is not None:
        handler.session.pop('user', None)

    # Build the redirect – must send_response() before any headers
    handler.send_response(302)
    handler.send_header('Location', config.LOGIN_ROUTE)

    # Clear the session cookie by setting Max-Age=0
    session.clear_session_cookie(handler)

    handler.end_headers()